﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Homework23
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            lblResult.Visible = false; // 初始状态下隐藏Label
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            string input = txtInput.Text.Trim(); // 获取输入的表达式并去除首尾空格
            if (string.IsNullOrEmpty(input))
            {
                MessageBox.Show("请输入有效的四则运算表达式！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                // 去除输入表达式中的空格
                input = RemoveSpaces(input);

                // 计算并输出结果
                double result = Calculate(input);
                lblResult.Text = "结果: " + result.ToString();
                lblResult.Visible = true; // 显示Label
            }
            catch (Exception ex)
            {
                MessageBox.Show("计算出错，请检查表达式是否正确：" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                lblResult.Visible = false; // 出错时隐藏Label
            }
        }

        // 去除表达式中的空格
        private static string RemoveSpaces(string expression)
        {
            return new string(expression.Where(c => !char.IsWhiteSpace(c)).ToArray());
        }

        // 计算表达式的结果
        private static double Calculate(string expression)
        {
            Stack<double> numbers = new Stack<double>(); // 操作数栈
            Stack<char> operations = new Stack<char>(); // 操作符栈
            char[] tokens = expression.ToCharArray();
            int index = 0;

            // 遍历表达式中的每个字符
            while (index < tokens.Length)
            {
                char token = tokens[index];
                // 如果是数字或小数点，则解析整个数字
                if (char.IsDigit(token) || token == '.')
                {
                    double number = ParseNumber(tokens, ref index);
                    numbers.Push(number); // 将解析的数字压入操作数栈
                }
                // 如果是左括号，压入操作符栈
                else if (token == '(')
                {
                    operations.Push(token);
                }
                // 如果是右括号，计算直到遇到左括号
                else if (token == ')')
                {
                    while (operations.Count > 0 && operations.Peek() != '(')
                    {
                        numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
                    }
                    operations.Pop(); // 弹出左括号
                }
                // 如果是操作符，根据优先级决定是否计算
                else if (token == '+' || token == '-' || token == '*' || token == '/')
                {
                    while (operations.Count > 0 && GetPrecedence(operations.Peek()) >= GetPrecedence(token))
                    {
                        numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
                    }
                    operations.Push(token); // 将操作符压入操作符栈
                }
                // 忽略空格
                else if (char.IsWhiteSpace(token))
                {
                    // 忽略空格
                }
                else
                {
                    // 遇到无效字符时抛出异常
                    throw new InvalidOperationException($"无效的字符：{token}");
                }
                index++; // 移动到下一个字符
            }

            // 计算剩余的操作
            while (operations.Count > 0)
            {
                numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
            }

            // 检查是否有未匹配的括号
            if (operations.Count != 0)
            {
                throw new InvalidOperationException("括号不匹配");
            }

            return numbers.Pop(); // 返回计算结果
        }

        // 解析数字（包括整数和小数）
        private static double ParseNumber(char[] tokens, ref int index)
        {
            double number = 0;
            double divisor = 1;
            bool isFractional = false;
            while (index < tokens.Length && (char.IsDigit(tokens[index]) || tokens[index] == '.'))
            {
                char currentChar = tokens[index];
                if (currentChar == '.' && !isFractional)
                {
                    isFractional = true;
                    divisor = 1; // 重置除数
                }
                else if (isFractional)
                {
                    number += (currentChar - '0') / (divisor * 10);
                    divisor *= 10;
                }
                else
                {
                    number = number * 10 + (currentChar - '0');
                }
                index++;
            }
            index--; // 回退一个字符，因为循环会多读一个
            return number;
        }

        // 获取操作符的优先级
        private static int GetPrecedence(char op)
        {
            if (op == '+' || op == '-')
            {
                return 1;
            }
            else if (op == '*' || op == '/')
            {
                return 2;
            }
            return 0;
        }

        // 应用操作符到两个操作数
        private static double ApplyOperation(double b, double a, char operation)
        {
            switch (operation)
            {
                case '+':
                    return a + b;
                case '-':
                    return a - b;
                case '*':
                    return a * b;
                case '/':
                    if (b == 0) throw new DivideByZeroException("除数不能为0");
                    return a / b;
            }
            throw new InvalidOperationException($"无效的操作符：{operation}");
        }
    }
}